 page
*
dealloc stx bmcnt ;save high order address of block to be freed.
 pha ;save it
 ldx vcbptr ; while the bitmap
 lda vcb+vcbtblk+1,x ; disk address is checked
 cmp bmcnt ; to see if it makes sense
 pla ; restore
 bcc dealerr1 ; branch if impossible
 tax
 and #$7 ;get the bit to be or-ed in.
 tay
 lda whichbit,y ;(shifting takes 7 bytes, but is slower)
 sta nofree ;save bit pattern
 txa ;get low block address again.
 lsr bmcnt
 ror a ;get pointer to byte in bitmap that represents
 lsr bmcnt ; the block address.
 ror a
 lsr bmcnt
 ror a
 sta bmptr ;save pointer.
 lsr bmcnt ;now transfer bit which specifies which page of bitmap.
 rol half
 jsr fndbmap ;make absolutely sure we've got the right device.
 bcs dealerr ;return any errors.
 lda bmacmap ; what is the current map
 cmp bmcnt ;is in-core bit map the one we want?
 beq deall1 ;branch if in-core is correct.
 jsr upbmap ;put current map away.
 bcs dealerr ;pass back any error.
 lda bmcnt ;get desired map number.
 ldx vcbptr 
 sta vcb+vcbcmap,x ;and make it current.
 lda bmadev 
 jsr gtbmap ;read it into the buffer,
 bcs dealerr
deall1 ldy bmptr ;index to byte.
 lsr half
 lda nofree ;(get individual bit)
 bcc deall2 ;branch if on page one of bitmap.
 ora bmbuf+$100,y 
 sta bmbuf+$100,y
 bcs deall3 ;branch always taken
deall2 equ * 
bmbufhi ora bmbuf,y
 sta bmbuf,y
deall3 lda #$80 ;mark bitmap as modified.
 ora bmastat 
 sta bmastat 
 inc deblock ;bump count of blocks deallocated
 bne deall4
 inc deblock+1
deall4 clc
dealerr rts
dealerr1 lda #bitmapadr ; bit map block number impossible
 sec ; say bit map disk address wrong
 rts ;   (probably data masquerading as index block)
 page
*
alc1blk jsr fndbmap ;get address of bit map in 'bmadr'
 bcs erralc1 ;branch if error encountered
srchfre ldy #0 ;start search at beginning of bit map block
 sty half ;indicate which half (page) we're searching.
getbits1 lda bmbuf,y
 bne bitfound ;free blocks are indicated by 'on' bits
 iny
 bne getbits1 ;check all of 'em in first page.
* 
 inc half ;indicate search has progressed to page 2
 inc basval ;base value= base address/2048
getbits2 lda bmbuf+$100,y ;search second half for free block
 bne bitfound
 iny
 bne getbits2
* 
 inc basval ; add 2048 offset for next page
 jsr nxtbmap ;get next bitmap (if it exists) and update vcb.
 bcc srchfre ;branch if no error encountered.
erralc1 rts ;return error.
 page
*
bitfound sty bmptr ;save indx pointer to valid bit group
 lda basval ;set up for block address calculation
 sta scrtch+1
 tya ;get address of bit pattern
 asl a ;multiply this and basval by 8
 rol scrtch+1
 asl a
 rol scrtch+1
 asl a
 rol scrtch+1
 tax ;now x= low address within 7 of actual address.
 sec
 lda half
 beq page1alc ;branch if allocating from 1st half
 lda bmbuf+$100,y ;get pattern from second page
 bcs adcalc ;branch always
page1alc lda bmbuf,y ;get bit pattern from first page  
adcalc rol a ;find left most 'on' bit
 bcs bounce ;branch if found.
 inx ;adjust low address
 bne adcalc ;branch always
bounce lsr a ;restore all but left most bit to original position
 bcc bounce ;loop until mark (set above) moves into carry
 stx scrtch ;save low address.
 ldx half ;which half of bit map?
 bne page2alc
 sta bmbuf,y
 beq drtybmap ;branch always
*
page2alc sta bmbuf+$100,y ;update bitmap to show allocated block in use.
drtybmap lda #$80 ;indicate map has been modified
 ora bmastat   
 sta bmastat ; by setting dirty bit. 
 ldy vcbptr ;subtract 1 from total free
 lda vcb+vcbtfre,y ; blocks in vcb to account for newly
 sbc #1 ; allocated block (carry is set from 'bounce')
 sta vcb+vcbtfre,y 
 bcs ret1blk ; branch if hi free count doesn't need adjustment.
* 
 lda vcb+vcbtfre+1,y ;adjust high count.
 sbc #0 ;(carry is clear, so acc=acc-1)
 sta vcb+vcbtfre+1,y
ret1blk clc ;indicate no error encountered
 lda scrtch ;get address low in acc.
 ldy scrtch+1 ;and high address in y
 rts ;return address of newly allocated block.
*
 page
nxtbmap ldy vcbptr ;before bumping to next map,
 lda vcb+vcbtblk+1,y ;check to be sure there is
 lsr a ; indeed a next map!
 lsr a
 lsr a
 lsr a
 cmp vcb+vcbcmap,y ;are there more maps?
 beq nomorbit ;branch if no more to look at.
 lda vcb+vcbcmap,y ;add 1 to current map
 clc
 adc #1
 sta vcb+vcbcmap,y
 jsr upbmap 
*
fndbmap ldy vcbptr ;get device number
 lda vcb+vcbdev,y 
 cmp bmadev 
 beq freshmap 
 jsr upbmap ;save out other volumes bitmap, and
 bcs nogo
 ldy vcbptr
 lda vcb+vcbdev,y
 sta bmadev ; read in fresh bitmap for this device.
freshmap equ * 
 ldy bmastat ;is this one already modified?
 bmi bmfound ;yes, return pointer in 'bmadr'
 jsr gtbmap ;otherwise read in fresh bit map
 bcs nogo ;branch if unsuccessful.
*
bmfound equ * 
 ldy vcbptr 
 lda vcb+vcbcmap,y
 asl a
 sta basval
 clc ;indicate all is valid and good!
nogo rts
*
nomorbit lda #ovrerr ;indicate request can't be filled.
 sec ;indicate error
 rts
*
upbmap clc ;anticipate nothing to do 
 lda bmastat ;is current map dirty? 
 bpl nogo ;no need to do anything
 jsr wrtbmap ;it is dirty, update device! 
 bcs nogo ; error encountered on writing
 lda #0
 sta bmastat ;mark bm buffer as free
 rts ;all done! 
*
*
gtbmap sta bmadev ;read bitmap specified by dev & vcb 
 ldy vcbptr ;get lowest map number with free blocks in it.
 lda vcb+vcbcmap,y
 sta bmacmap ; associate the offset with the bitmap control block
 clc ;add this number to the base
 adc vcb+vcbdmap,y ; address of first bit map
 sta bmadadr ;save low address of bit map to be used.
 lda vcb+vcbdmap+1,y ;now get high disk address of map
 adc #0 ;add to this the state of the carry
 sta bmadadr+1 ;save high disk address too.
*
 lda #rdcmd ;(x contains an index to determine which buffer)
dobmap sta dhpcmd ;save device command
 lda devnum ; preserve current devnum. 
 pha 
 lda bmadev ;get bitmap's device number.
 sta devnum
 lda bmadadr ;and map's disk address
 sta bloknml
 lda bmadadr+1 
 sta bloknmh
 lda bmbufhi+2 ;lastly get the address of the buffer
 jsr dobitmap ;(note: low address is fixed to zero as this is a buffer)
 tax ;preserve error code, if any.
 pla ; restore
 sta devnum ; the devnum we came in with!
 bcc dobmap1 ;return devnum if no error.
 txa ;return any errors.
dobmap1 rts
*
rdblk equ *
 sta bloknml
 stx bloknmh
 jsr rdgbuf
 rts
*
wrtbmap lda #wrtcmd ;write bit map. 
 bne dobmap ;branch always 
*
wrtgbuf lda #wrtcmd ;set call for write.
 bne svgcmd ;branch always.
rdgbuf lda #rdcmd ;set call for read.
svgcmd sta dhpcmd ;passed to device handler.
 lda #<gbuf ;get high address of general buffer
dobitmap php ;no interupts allowed 
 sei
 sta dbufph 
 lda #0 ;general purpose buffers always
 sta dbufpl ; start on a page boundary.
 sta serr ; clear global error value
 lda #$ff ;also, 
 sta ioaccess ; set to indicate reg call made to dev handler. 
 lda devnum ;transfer the device number for dispatcher to convert to unit number.
 sta unitnum
 jsr dmgr ; call the driver
 bcs fioerr1 ;branch if error
 plp ;restore interupts.
 clc
 rts
fioerr1 plp ;restore interupts
 sec
 rts
*
